# I2C LCD驱动库
# 来源：https://gitcode.com/mirrors/dhylands/python_lcd
from machine import I2C
from lcd_api import LcdApi

# PCF8574 I2C地址（通常为0x27或0x3F）
DEFAULT_I2C_ADDR = 0x27

class I2cLcd(LcdApi):
    # PCF8574引脚映射
    MASK_RS = 0x01       # P0
    MASK_RW = 0x02       # P1
    MASK_E  = 0x04       # P2
    SHIFT_BACKLIGHT = 3  # P3
    SHIFT_DATA = 4       # P4-P7

    def __init__(self, i2c, i2c_addr, num_lines, num_columns):
        self.i2c = i2c
        self.i2c_addr = i2c_addr
        self.num_lines = num_lines
        self.num_columns = num_columns
        
        # 初始化I2C
        self.write_cmd(0x03)
        self.write_cmd(0x03)
        self.write_cmd(0x03)
        self.write_cmd(LcdApi.LCD_FUNCTION | LcdApi.LCD_FUNCTION_2LINES)
        LcdApi.__init__(self, num_lines, num_columns)
    
    def write_cmd(self, cmd):
        # 发送命令
        buf = bytearray(2)
        buf[0] = (cmd >> 4) << self.SHIFT_DATA
        buf[1] = (cmd & 0x0F) << self.SHIFT_DATA
        self.send(buf[0], self.MASK_E)
        self.send(buf[1], self.MASK_E)
    
    def write_data(self, data):
        # 发送数据
        buf = bytearray(2)
        buf[0] = self.MASK_RS | (data >> 4) << self.SHIFT_DATA
        buf[1] = self.MASK_RS | (data & 0x0F) << self.SHIFT_DATA
        self.send(buf[0], self.MASK_E)
        self.send(buf[1], self.MASK_E)
    
    def send(self, data, mask):
        # 发送数据到I2C
        data |= mask
        if self.backlight:
            data |= 1 << self.SHIFT_BACKLIGHT
        self.i2c.writeto(self.i2c_addr, bytes([data | 0x04]))  # 拉高E
        self.hal_sleep_us(1)
        self.i2c.writeto(self.i2c_addr, bytes([data]))          # 拉低E
        self.hal_sleep_us(1)
    
    def hal_write_command(self, cmd):
        self.write_cmd(cmd)
    
    def hal_write_data(self, data):
        self.write_data(data)
    
    def hal_backlight_on(self):
        self.i2c.writeto(self.i2c_addr, bytes([1 << self.SHIFT_BACKLIGHT]))
    
    def hal_backlight_off(self):
        self.i2c.writeto(self.i2c_addr, bytes([0]))
